#!/anaconda3/envs/Script/bin python3.8
# -*- coding: utf-8 -*-
# ---
# @Software: PyCharm
# @File: base_model.py
# @Author: AllenFu
# @Institution: NCHU, China
# @E-mail: nchufujianjian@126.com
# @Site: 基础模型
# @Time: 11月 27, 2020
# ---
import math

from sqlalchemy import desc, asc

from app import dBSession
from app.vendor.res_code import Code


class BaseModel:

    def get_list(self, cls_: object, filters: set, order: str = 'id desc', field: tuple = (), offset: int = 0,
                 limit: int = 15) -> dict:
        '''
        获取列表
        :param cls_ 数据库模型实体类
        :param filters 查询条件
        :param order 排序
        :param field 字典
        :param offset 偏移量
        :param limit 取多少条
        '''
        total_count = dBSession.query(cls_).filter(*filters).count()
        res = {
            'page': {
                'count': total_count,
                'total_page': self.get_page_number(total_count, limit),
                'current_page': offset,
            },
            'list': [],
        }
        if offset != 0:
            offset = (offset - 1) * limit

        if res['page']['count'] > 0:
            res['list'] = dBSession.query(cls_).filter(*filters)
            order_arr = order.split(' ')
            if order_arr[1] == 'desc':
                res['list'] = res['list'].order_by(desc(order_arr[0])).offset(offset).limit(limit).all()
            else:
                res['list'] = res['list'].order_by(asc(order_arr[0])).offset(offset).limit(limit).all()
        if not field:
            res['list'] = [c.to_dict() for c in res['list']]
        else:
            res['list'] = [c.to_dict(only=field) for c in res['list']]

        return res

    def get_all(self, cls_: object, filters: set, order: str = 'id desc', field: tuple = (), limit: int = 0) -> list:
        '''
        查询全部
        :param object cls_ 数据库模型实体类
        :param set filters 查询条件
        :param str order 排序
        :param tuple field 字段
        :param int $limit 取多少条
        :return dict
        '''
        if not filters:
            res = dBSession.query(cls_)
        else:
            res = dBSession.query(cls_).filter(*filters)

        if limit:
            res = res.limit(limit)

        order_arr = order.split(' ')
        if order_arr[1] == 'desc':
            res = res.order_by(desc(order_arr[0])).all()
        else:
            res = res.order_by(asc(order_arr[0])).all()

        if field:
            res = [c.to_dict(only=field) for c in res]
        else:
            res = [c.to_dict() for c in res]

        return res

    def getOne(self, cls_: object, filters: set, order: str = 'id desc', field: tuple = ()):
        """
        获取一条
        @param object cls_ 数据库模型实体类
        @param set filters 查询条件
        @param str order 排序
        @param tuple field 字段
        @return dict
        """
        res = dBSession.query(cls_).filter(*filters)
        order_arr = order.split(' ')
        if order_arr[1] == 'desc':
            res = res.order_by(desc(order_arr[0])).first()
        else:
            res = res.order_by(asc(order_arr[0])).first()
        if not res:
            return None
        if not field:
            res = res.to_dict()
        else:
            res = res.to_dict(only=field)
        return res

    def add(self, cls_, data: dict) -> int:
        """
        添加
        @param object cls_ 数据库模型实体类
        @param dict data 数据
        @return bool
        """
        users = cls_(**data)
        dBSession.add(users)
        dBSession.flush()
        return users.id

    def edit(self, cls_: object, data: dict, filters: set) -> bool:
        """
        修改
        @param object cls_ 数据库模型实体类
        @param dict data 数据
        @param set filters 条件
        @return bool
        """
        return dBSession.query(cls_).filter(*filters).update(data, synchronize_session=False)

    def delete(self, cls_: object, filters: set) -> int:
        """
        删除
        @param object cls_ 数据库模型实体类
        @param set filters 条件
        @return int
        """
        return dBSession.query(cls_).filter(*filters).delete(synchronize_session=False)

    def getCount(self, cls_: object, filters: set, field=None) -> int:
        """
        统计数量
        @param object cls_ 数据库模型实体类
        @param set filters 条件
        @param obj field 字段
        @return int
        """
        if field == None:
            return dBSession.query(cls_).filter(*filters).count()
        else:
            return dBSession.query(cls_).filter(*filters).count(field)

    @staticmethod
    def get_page_number(count: int, page_size: int) -> int:
        """
        * 获取总页数
        * @param int count
        * @param int page_size
        * @return int
        """
        page_size = abs(page_size)
        if page_size != 0:
            total_page = math.ceil(count / page_size)
        else:
            total_page = math.ceil(count / 5)
        return total_page



    @staticmethod
    def formatPaged(page, size, total):
        """
        格式化分页
        @param int page
        @param int size
        @param int total
        @return dict
        """
        if int(total) > int(page) * int(size):
            more = 1
        else:
            more = 0
        return {
            'total': int(total),
            'page': int(page),
            'size': int(size),
            'more': more
        }



    @staticmethod
    def formatBody(data={}, msg='', show=True):
        """
        格式化返回体
        @param dict data
        @return dict
        """
        dataformat = {}
        dataformat['error_code'] = Code.SUCCESS
        dataformat['data'] = data
        dataformat['msg'] = msg
        dataformat['show'] = show
        return dataformat

    @staticmethod
    def formatError(code, message='', show=True):
        """
        格式化错误返回体
        @param int code
        @param string message
        @return dict
        """
        if code == Code.BAD_REQUEST:
            message = 'Bad request.'
        elif code == Code.NOT_FOUND:
            message = 'No result matched.'
        body = {}
        body['error'] = True
        body['error_code'] = Code.BAD_REQUEST
        body['msg'] = message
        body['show'] = show
        return body
